﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace Utility.Utils
{

    public class SequentialGuidGenerator
    {
        private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create();
        private static object syncLocker = new object();

        public static Guid NewSequentialGuid(SequentialGuidType guidType)
        {
            lock (syncLocker)
            {
                byte[] array = new byte[10];
                _rng.GetBytes(array);
                byte[] bytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks / 10000);
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(bytes);
                }
                byte[] array2 = new byte[16];
                switch (guidType)
                {
                    case SequentialGuidType.SequentialAsString:
                    case SequentialGuidType.SequentialAsBinary:
                        Buffer.BlockCopy(bytes, 2, array2, 0, 6);
                        Buffer.BlockCopy(array, 0, array2, 6, 10);
                        if (guidType == SequentialGuidType.SequentialAsString && BitConverter.IsLittleEndian)
                        {
                            Array.Reverse(array2, 0, 4);
                            Array.Reverse(array2, 4, 2);
                        }
                        break;
                    case SequentialGuidType.SequentialAtEnd:
                        Buffer.BlockCopy(array, 0, array2, 0, 10);
                        Buffer.BlockCopy(bytes, 2, array2, 10, 6);
                        break;
                }
                return new Guid(array2);
            }
        }
    }


    public enum SequentialGuidType
    {
        SequentialAsString,
        SequentialAsBinary,
        SequentialAtEnd
    }
}
